#include <cassert>

#include "trapezoidmf.h"

TrapezoidMF::TrapezoidMF() : GraphicalMF("Trapezoid", 4)
{
    /* Set the x values */
    for(int i = 0; i < m_size; ++i)
    {
        m_points[i].setX(i);
    }

    /* Set the y values */
    m_points[0].setY(0);
    m_points[1].setY(1);
    m_points[2].setY(1);
    m_points[3].setY(0);
}

TrapezoidMF::TrapezoidMF(double newPoints[]) : GraphicalMF("Trapezoid", 4)
{
    /* Set the x values in accordance to the array that was passed in */
    for( int i = 0; i < m_size; ++i )
        m_points[i].setX(newPoints[i]);

    /* Set the y values */
    m_points[0].setY(0);
    m_points[1].setY(1);
    m_points[2].setY(1);
    m_points[3].setY(0);
}

TrapezoidMF::~TrapezoidMF()
{
}

void TrapezoidMF::paint(QPainter *painter, const double &xShift,
                        const double &xScale, const double &yShift,
                        const double &yScale) const
{
    /* Paint in the generic GraphicalMF style */
    this->GraphicalMF::paint(painter, xShift, xScale, yShift, yScale);

    /* Draw the name of the MF above it and near the center */
    /* This would be better drawn attached to the top point, in my mind.*/
    painter->drawText(xShift + xScale * (m_points[2].x() + m_points[0].x())/2,
                      yShift + yScale - 4,
                      this->getName());

    /* If this is an output MF, draw the composite */
    if( m_is_output && m_fuzzy_value <= 1 ) {

        /* If the degree of membership of this set is 0, there is nothing to
         * draw.
         */
        if( m_fuzzy_value == 0 ) return;

        /* m_fuzzy_value is what holds the probability, so we're working with
         * that.
         */
        double p = m_fuzzy_value;
        double np = 1 - p;
        double x[] = { m_points[0].x(),
                       m_points[1].x(),
                       m_points[2].x(),
                       m_points[3].x() };
        double y[] = { m_points[0].y(),
                       m_points[1].y(),
                       m_points[2].y(),
                       m_points[3].y() };

        QPointF p1(xShift + xScale * x[0], yShift + yScale * y[0]);

        QPointF p2(xShift + xScale * (x[1] * p + x[0] * np),
                   yShift + yScale * y[1] * p);

        QPointF p3(xShift + xScale * (x[3] * np + x[2] * p), p2.y());

        QPointF p4(xShift + xScale * x[3], yShift + yScale * y[3]);

        QPointF points[] = {p1, p2, p3, p4, p1};

        QBrush oldBrush = painter->brush();
        painter->setBrush(Qt::blue);
        painter->drawPolygon(points, 5);
        painter->setBrush(oldBrush);
    }

}

void TrapezoidMF::calculateCentroid()
{

    double x1 = m_points[0].x() + (m_points[1].x() - m_points[0].x())*2.0/3;
    double x2 = m_points[1].x() + (m_points[2].x() - m_points[1].x())*1.0/2;
    double x3 = m_points[2].x() + (m_points[3].x() - m_points[2].x())*1.0/3;

    m_crisp_value = (x1 + x2 + x3) / 3;

}

void TrapezoidMF::calculateProbability(const double& crispInput)
{
    if (crispInput <= m_points[0].x() || crispInput >= m_points[3].x())
    {
        m_fuzzy_value = 0;
    }
    else if (crispInput > m_points[0].x() && crispInput < m_points[1].x())
    {
        m_fuzzy_value = (crispInput - m_points[0].x()) / (m_points[1].x() - m_points[0].x());
    }
    else if(crispInput >= m_points[1].x() && crispInput <= m_points[2].x())
    {
        m_fuzzy_value = 1;
    }
    else if(crispInput > m_points[2].x() && crispInput <= m_points[3].x())
    {
        m_fuzzy_value = (m_points[3].x() - crispInput) / (m_points[3].x() - m_points[2].x());
    }
}
